<template>
  <div class="upload-file-component">
    <!-- 文件上传组件 -->
    <el-upload
      ref="uploadRef"
      :action="action"
      :auto-upload="autoUpload"
      :multiple="multiple"
      :limit="limit"
      :file-list="fileList"
      :list-type="listType"
      :http-request="customUpload"
      :before-upload="beforeUpload"
      :on-preview="handlePreview"
      :on-remove="handleRemove"
      :on-exceed="handleExceed"
      :on-success="handleSuccess"
      :on-error="handleError"
      :disabled="disabled"
      :accept="accept"x
      :show-file-list="showFileList"
      :drag="drag"
      :class="{ 'hide-upload-button': fileList.length >= limit && !multiple }"
    >
      <template v-if="drag">
        <el-icon class="el-icon--upload"><upload-filled /></el-icon>
        <div class="el-upload__text">{{ $t('uploadVideo.将视频拖到此处或') }}<em>{{ $t('uploadVideo.点击上传') }}</em></div>
      </template>
      <template v-else>
        <el-icon class="el-icon--upload"><Plus /></el-icon>
      </template>
      <template #tip>
        <div class="el-upload__tip" v-if="showTip">
          {{ tipText }}
        </div>
      </template>
      <template #file="{ file, index }">
        <div class="flex_aic_jcc h-full w-full" v-if="loading">
          <el-icon size="20"><Loading /></el-icon>
        </div>
        <div class="w-full h-full flex_aic_jcc meskArea" v-else>
          <el-icon size="20"><VideoCameraFilled /></el-icon>
          <div class="w-full h-full flex_aic_jcc gap-24 opeaIcon">
            <el-icon @click="handlePreview(file)" class="cursor-pointer" size="20" color="#ffffff"><ZoomIn /></el-icon>
            <el-icon @click="handleRemove(file, index)" class="cursor-pointer" size="20" color="#ffffff"><Delete /></el-icon>
          </div>
        </div>
      </template>
    </el-upload>

    <!-- 视频预览对话框 -->
    <el-dialog v-model="previewVisible" :title="$t('uploadVideo.视频预览')" width="800px">
      <div class="flex_aic_jcc w-full h-full">
        <video
          :src="previewUrl"
          controls
          style="max-width: 80%; max-height: 500px;"
          v-if="previewUrl"
        ></video>
      </div>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, computed, watch, onMounted } from "vue";
import { UploadFilled, Plus, VideoCameraFilled, ZoomIn, Delete, Loading } from "@element-plus/icons-vue";
import { ElMessage, ElMessageBox } from "element-plus";
import axios from "axios";
import Config from "@/config/env";
import { useI18n } from 'vue-i18n';

const { t } = useI18n();
const loading = ref(false);
const props = defineProps({
  // 接口地址
  action: {
    type: String,
    default: "/api/file/video",
  },
  // 是否自动上传
  autoUpload: {
    type: Boolean,
    default: true,
  },
  // 是否支持多选文件
  multiple: {
    type: Boolean,
    default: false,
  },
  // 上传数量限制
  limit: {
    type: Number,
    default: 1,
  },
  // 文件列表的类型 (text, picture, picture-card)
  listType: {
    type: String,
    default: "picture-card",
  },
  // 使用modelValue接收v-model绑定值
  modelValue: {
    type: Array,
    default: () => [],
  },
  // 是否禁用
  disabled: {
    type: Boolean,
    default: false,
  },
  // 接受上传的文件类型
  accept: {
    type: String,
    default: "video/mp4",
  },
  // 文件大小限制，单位MB
  fileSize: {
    type: Number,
    default: 50,
  },
  // 是否显示已上传文件列表
  showFileList: {
    type: Boolean,
    default: true,
  },
  // 是否启用拖拽上传
  drag: {
    type: Boolean,
    default: false,
  },
  // 按钮文本
  buttonText: {
    type: String,
    default: "点击上传",
  },
  // 是否显示提示文本
  showTip: {
    type: Boolean,
    default: true,
  },
  // 上传接口的请求头
  headers: {
    type: Object,
    default: () => ({}),
  },
  // 上传接口的额外参数
  data: {
    type: Object,
    default: () => ({}),
  },
  // 文件字段名
  name: {
    type: String,
    default: "file",
  },
  // 上传请求的方法
  method: {
    type: String,
    default: "post",
  },
});

const emit = defineEmits([
  "update:modelValue",
  "success",
  "error",
  "exceed",
  "remove",
  "preview",
  "change",
]);

// 上传组件引用
const uploadRef = ref(null);

// 文件列表 - 只在内部使用
const fileList = ref([]);

// 预览相关
const previewVisible = ref(false);
const previewUrl = ref("");

// 提示文本
const tipText = computed(() => {
  return t('uploadVideo.请上传视频格式', { size: props.fileSize, limit: props.limit });
});

// 初始化及同步外部传入的值到内部fileList
watch(
  () => props.modelValue,
  (newVal) => {
    if (!newVal || newVal.length === 0) {
      fileList.value = [];
      return;
    }

    fileList.value = newVal.map((item, index) => {
      // 如果是字符串URL，转为对象格式
      if (typeof item === "string") {
        return {
          name: `${t('uploadVideo.视频')}${index + 1}`,
          url: item,
        };
      }
      // 如果已经是对象
      else if (typeof item === "object") {
        // 有url就返回原对象
        if (item.url) {
          return item;
        }
        // 处理后端返回的响应数据，将其转换为组件需要的格式
        if (item.response) {
          const responseData = item.response;
          return {
            ...item,
            url: responseData.data.url || "",
            name: responseData.data.filename || `${t('uploadVideo.视频')}${index + 1}`,
          };
        }
      }
      return item;
    });
  },
  { immediate: true, deep: true }
);

// 视频预览
const handlePreview = (file) => {
  previewUrl.value =
    file.url ||
    (file.response && file.response.data.url) ||
    URL.createObjectURL(file.raw);
  previewVisible.value = true;
  emit("preview", file);
};

// 移除视频
const handleRemove = (file, uploadFiles) => {
  fileList.value = fileList.value.filter((item) => item.url !== file.url);
  updateModelValue(fileList.value);
  emit("remove", file, uploadFiles);
};

// 超出上传数量限制时的处理
const handleExceed = (files, uploadFiles) => {
  ElMessage.warning(
    t('uploadVideo.上传限制提示', { limit: props.limit, selected: files.length, total: uploadFiles.length + files.length })
  );
  emit("exceed", files, uploadFiles);
};

// 上传成功回调
const handleSuccess = (response, file, uploadFiles) => {
  ElMessage.success(t('uploadVideo.视频上传成功'));
  console.log(1111, response, file, uploadFiles);
  loading.value = false;
  // 更新文件url (从响应中获取)
  if (response) {
    const url = response.data.url || "";
    console.log(url);

    if (url) {
      file.url = url;
    }
  }

  // 同步到父组件
  updateModelValue(uploadFiles);
  emit("success", response, file, uploadFiles);
};

// 上传失败回调
const handleError = (error, file, uploadFiles) => {
  ElMessage.error(t('uploadVideo.视频上传失败'));
  console.error("上传失败:", error);
  emit("error", error, file, uploadFiles);
};

// 更新modelValue的函数
const updateModelValue = (files) => {
  const valueToEmit = files.map((file) => {
    // 如果已有url，直接返回url
    if (file.url) {
      return { url: file.url, name: file.name };
    }
    // 如果是刚上传的文件，从响应中获取url
    else if (file.response) {
      const url = file.response.data.url;
      const name = file.response.data.filename || file.name;
      return { url, name };
    }
    // 回退方案
    return file;
  });

  emit("update:modelValue", valueToEmit);
  emit("change", valueToEmit);
};

// 上传前的校验
const beforeUpload = (file) => {
  // 检查文件类型
  const fileType = file.type;
  if (fileType !== "video/mp4") {
    ElMessage.error(t('uploadVideo.只能上传MP4格式'));
    return false;
  }

  // 检查文件大小
  const isLtSize = file.size / 1024 / 1024 < props.fileSize;
  if (!isLtSize) {
    ElMessage.error(t('uploadVideo.视频大小不能超过', { size: props.fileSize }));
    return false;
  }

  return true;
};

// 自定义上传方法
const customUpload = async (options) => {
  const { file, onProgress, onSuccess, onError } = options;
  loading.value = true;
  // 创建 FormData 对象，添加文件和额外数据
  const formData = new FormData();
  formData.append(props.name, file);

  // 添加额外数据
  Object.keys(props.data).forEach((key) => {
    formData.append(key, props.data[key]);
  });

  try {
    const token = Storage.get("token", true);
    const config = {
      headers: {
        "Content-Type": "multipart/form-data",
        Authorization: token,
        "Accept-Language": "zh_CN",
        ...props.headers,
      },
      onUploadProgress: (progressEvent) => {
        // 计算上传进度
        const percent = Math.round(
          (progressEvent.loaded * 100) / progressEvent.total
        );
        onProgress({ percent });
      },
    };

    // 发送上传请求
    const response = await axios({
      method: props.method,
      url: props.action,
      data: formData,
      ...config,
    });

    // 获取响应数据
    const responseData = response.data;

    // 上传成功
    onSuccess(responseData);
    return responseData;
  } catch (error) {
    // 上传失败
    onError(error);
    return Promise.reject(error);
  }
};

// 手动上传方法
const submitUpload = () => {
  if (uploadRef.value) {
    uploadRef.value.submit();
  }
};

// 清空上传列表
const clearFiles = () => {
  if (uploadRef.value) {
    uploadRef.value.clearFiles();
    fileList.value = [];
    emit("update:modelValue", []);
    emit("change", []);
  }
};

// 暴露方法供父组件调用
defineExpose({
  submitUpload,
  clearFiles,
  uploadRef,
});
</script>

<style scoped>
.upload-file-component {
  width: 100%;
}

.hide-upload-button :deep(.el-upload--picture-card) {
  display: none;
}

.el-upload__tip {
  font-size: 12px;
  color: #606266;
  margin-top: 5px;
}

:deep(.el-upload-list--picture-card .el-upload-list__item),
:deep(.el-upload--picture-card) {
  width: 146px;
  height: 146px;
}

.meskArea{
  .opeaIcon{
    display: none;
    position: absolute;
    top: 0;
    left: 0;
    background-color: rgba(0, 0, 0, 0.4);
  }
  &:hover{
    .opeaIcon{
      display: flex;
    }
  }
}
</style>
